BatteryMonitor.cpp revision d5fe6675a73c3a831d0c4e41343ee86772633db8
1752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor/*
2752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * Copyright (C) 2013 The Android Open Source Project
3752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor *
4752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * Licensed under the Apache License, Version 2.0 (the "License");
5752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * you may not use this file except in compliance with the License.
6752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * You may obtain a copy of the License at
7752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor *
8752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor *      http://www.apache.org/licenses/LICENSE-2.0
9752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor *
10752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * Unless required by applicable law or agreed to in writing, software
11752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * distributed under the License is distributed on an "AS IS" BASIS,
12752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * See the License for the specific language governing permissions and
14752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor * limitations under the License.
15752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor */
16752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
17752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define LOG_TAG "healthd"
18752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
1910b235e7436256da9adc827125645f141bd8fac9Todd Poynor#include "healthd.h"
20752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include "BatteryMonitor.h"
21752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
22752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <dirent.h>
23752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <errno.h>
24752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <fcntl.h>
25752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <stdio.h>
26752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <stdlib.h>
27752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <unistd.h>
28752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <batteryservice/BatteryService.h>
29752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <cutils/klog.h>
303db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor#include <cutils/properties.h>
31e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor#include <sys/types.h>
32c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor#include <utils/Errors.h>
33752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/String8.h>
34752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/Vector.h>
35752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
36752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SUBSYSTEM "power_supply"
37752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
38a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi#define FAKE_BATTERY_CAPACITY 42
39a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi#define FAKE_BATTERY_TEMPERATURE 424
40752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
41752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynornamespace android {
42752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
43752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstruct sysfsStringEnumMap {
446f5b47f9144960412b0fb6bc417f0c41bf53438aMark Salyzyn    const char* s;
45752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int val;
46752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor};
47752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
48752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstatic int mapSysfsString(const char* str,
49752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                          struct sysfsStringEnumMap map[]) {
50752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    for (int i = 0; map[i].s; i++)
51752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (!strcmp(str, map[i].s))
52752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            return map[i].val;
53752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
54752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return -1;
55752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
56752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
57752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryStatus(const char* status) {
58752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
59752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryStatusMap[] = {
60752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_STATUS_UNKNOWN },
61752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Charging", BATTERY_STATUS_CHARGING },
62752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Discharging", BATTERY_STATUS_DISCHARGING },
63752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
64752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Full", BATTERY_STATUS_FULL },
65752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
66752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
67752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
68752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryStatusMap);
69752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
70752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
71752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_STATUS_UNKNOWN;
72752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
73752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
74752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
75752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
76752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
77752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryHealth(const char* status) {
78752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
79752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryHealthMap[] = {
80752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_HEALTH_UNKNOWN },
81752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Good", BATTERY_HEALTH_GOOD },
82752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Overheat", BATTERY_HEALTH_OVERHEAT },
83752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Dead", BATTERY_HEALTH_DEAD },
84752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
85752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
86752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Cold", BATTERY_HEALTH_COLD },
87752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
88752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
89752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
90752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryHealthMap);
91752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
92752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
93752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_HEALTH_UNKNOWN;
94752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
95752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
96752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
97752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
98752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
99752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
100752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char *cp = NULL;
101752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
102752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (path.isEmpty())
103752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
104752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int fd = open(path.string(), O_RDONLY, 0);
105752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (fd == -1) {
106752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
107752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
108752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
109752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
110752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
111752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (count > 0)
112752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            cp = (char *)memrchr(buf, '\n', count);
113752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
114752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (cp)
115752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        *cp = '\0';
116752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
117752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        buf[0] = '\0';
118752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
119752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    close(fd);
120752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return count;
121752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
122752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
123752faf2c18407fd79127fb3f3773910b4ddf669dTodd PoynorBatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
124752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
125752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
126752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int length = readFromFile(path, buf, SIZE);
127752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    BatteryMonitor::PowerSupplyType ret;
128752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap supplyTypeMap[] = {
129752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
130752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
131752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
132752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
133752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
134752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
135752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
136752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
137752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
138752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { NULL, 0 },
139752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
140752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
141752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (length <= 0)
142752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
143752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
144752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
145752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0)
146752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
147752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
148752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
149752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
150752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
151752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::getBooleanField(const String8& path) {
152752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 16;
153752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
154752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
155752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    bool value = false;
156752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
157752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (buf[0] != '0') {
158752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            value = true;
159752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
160752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
161752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
162752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
163752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
164752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
165752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getIntField(const String8& path) {
166752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
167752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
168752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
169752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int value = 0;
170752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
171752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        value = strtol(buf, NULL, 0);
172752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
173752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
174752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
175752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
176752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::update(void) {
17710b235e7436256da9adc827125645f141bd8fac9Todd Poynor    bool logthis;
178752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
179752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerAcOnline = false;
180752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerUsbOnline = false;
181752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerWirelessOnline = false;
182752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
183752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
184d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos    props.maxChargingCurrent = 0;
185752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
186f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    if (!mHealthdConfig->batteryPresentPath.isEmpty())
187f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor        props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
188752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
1896dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        props.batteryPresent = mBatteryDevicePresent;
190752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
1913db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor    props.batteryLevel = mBatteryFixedCapacity ?
1923db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor        mBatteryFixedCapacity :
1933db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor        getIntField(mHealthdConfig->batteryCapacityPath);
194f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
195b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
1963db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor    props.batteryTemperature = mBatteryFixedTemperature ?
1973db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor        mBatteryFixedTemperature :
1983db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor        getIntField(mHealthdConfig->batteryTemperaturePath);
199752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
200752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
201752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
202752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 btech;
203752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
204f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
205752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryStatus = getBatteryStatus(buf);
206752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
207f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
208752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryHealth = getBatteryHealth(buf);
209752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
210f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
211752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryTechnology = String8(buf);
212752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
213752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    unsigned int i;
214752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
215752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    for (i = 0; i < mChargerNames.size(); i++) {
216752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        String8 path;
217752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
218752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                          mChargerNames[i].string());
219752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
220752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (readFromFile(path, buf, SIZE) > 0) {
221752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            if (buf[0] != '0') {
222752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
223752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
224752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                                  mChargerNames[i].string());
225752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                switch(readPowerSupplyType(path)) {
226752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_AC:
227752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerAcOnline = true;
228752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
229752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_USB:
230752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerUsbOnline = true;
231752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
232752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
233752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerWirelessOnline = true;
234752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
235752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                default:
236752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
237752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                                 mChargerNames[i].string());
238752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
239d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                path.clear();
240d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
241d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                                  mChargerNames[i].string());
242d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                if (access(path.string(), R_OK) == 0) {
243d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                    int maxChargingCurrent = getIntField(path);
244d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                    if (props.maxChargingCurrent < maxChargingCurrent) {
245d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                        props.maxChargingCurrent = maxChargingCurrent;
246d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                    }
247d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos                }
248752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
249752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
250752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
251752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
25210b235e7436256da9adc827125645f141bd8fac9Todd Poynor    logthis = !healthd_board_battery_update(&props);
253b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
25410b235e7436256da9adc827125645f141bd8fac9Todd Poynor    if (logthis) {
25510b235e7436256da9adc827125645f141bd8fac9Todd Poynor        char dmesgline[256];
2566dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor
257c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor        if (props.batteryPresent) {
2586dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            snprintf(dmesgline, sizeof(dmesgline),
25910b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
26010b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryLevel, props.batteryVoltage,
26110b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryTemperature < 0 ? "-" : "",
26210b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 abs(props.batteryTemperature / 10),
26310b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 abs(props.batteryTemperature % 10), props.batteryHealth,
26410b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryStatus);
265b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
266c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor            if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
267c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor                int c = getIntField(mHealthdConfig->batteryCurrentNowPath);
268c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor                char b[20];
26910b235e7436256da9adc827125645f141bd8fac9Todd Poynor
270c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor                snprintf(b, sizeof(b), " c=%d", c / 1000);
271c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor                strlcat(dmesgline, b, sizeof(dmesgline));
272c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor            }
273c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor        } else {
274c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor            snprintf(dmesgline, sizeof(dmesgline),
275c15e9934675d2f6b8dc19f042e6d045415e79359Todd Poynor                 "battery none");
27610b235e7436256da9adc827125645f141bd8fac9Todd Poynor        }
277b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
278ebeb0c0ea63af9fd8b2c8a7a20f919e48098ad9aTodd Poynor        KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
279ebeb0c0ea63af9fd8b2c8a7a20f919e48098ad9aTodd Poynor                     props.chargerAcOnline ? "a" : "",
280ebeb0c0ea63af9fd8b2c8a7a20f919e48098ad9aTodd Poynor                     props.chargerUsbOnline ? "u" : "",
281ebeb0c0ea63af9fd8b2c8a7a20f919e48098ad9aTodd Poynor                     props.chargerWirelessOnline ? "w" : "");
28210b235e7436256da9adc827125645f141bd8fac9Todd Poynor    }
283752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
284c7464c9150eb63ad277cc5b5f704f4fd5e6678c5Todd Poynor    healthd_mode_ops->battery_update(&props);
285752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return props.chargerAcOnline | props.chargerUsbOnline |
286752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            props.chargerWirelessOnline;
287752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
288752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
289c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynorstatus_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
290c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    status_t ret = BAD_VALUE;
291c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor
2928f132af495d208272ea55d0ca24068926fa80e51Todd Poynor    val->valueInt64 = LONG_MIN;
2938f132af495d208272ea55d0ca24068926fa80e51Todd Poynor
294c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    switch(id) {
295c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    case BATTERY_PROP_CHARGE_COUNTER:
296c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
2978f132af495d208272ea55d0ca24068926fa80e51Todd Poynor            val->valueInt64 =
298c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor                getIntField(mHealthdConfig->batteryChargeCounterPath);
299c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor            ret = NO_ERROR;
300c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        } else {
301c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor            ret = NAME_NOT_FOUND;
302c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        }
303c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        break;
304c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor
305c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    case BATTERY_PROP_CURRENT_NOW:
306c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
3078f132af495d208272ea55d0ca24068926fa80e51Todd Poynor            val->valueInt64 =
308c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor                getIntField(mHealthdConfig->batteryCurrentNowPath);
309c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor            ret = NO_ERROR;
310c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        } else {
311c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor            ret = NAME_NOT_FOUND;
312c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        }
313c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        break;
314c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor
315bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor    case BATTERY_PROP_CURRENT_AVG:
316bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor        if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
3178f132af495d208272ea55d0ca24068926fa80e51Todd Poynor            val->valueInt64 =
318bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                getIntField(mHealthdConfig->batteryCurrentAvgPath);
319bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor            ret = NO_ERROR;
320bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor        } else {
321bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor            ret = NAME_NOT_FOUND;
322bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor        }
323bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor        break;
324bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor
325347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence    case BATTERY_PROP_CAPACITY:
326347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence        if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
3278f132af495d208272ea55d0ca24068926fa80e51Todd Poynor            val->valueInt64 =
328347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence                getIntField(mHealthdConfig->batteryCapacityPath);
329347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence            ret = NO_ERROR;
330347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence        } else {
331347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence            ret = NAME_NOT_FOUND;
332347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence        }
333347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence        break;
334347c8de285454af2d3cba3d9b43d3bf23b20babbPaul Lawrence
3358f132af495d208272ea55d0ca24068926fa80e51Todd Poynor    case BATTERY_PROP_ENERGY_COUNTER:
336e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor        if (mHealthdConfig->energyCounter) {
337e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor            ret = mHealthdConfig->energyCounter(&val->valueInt64);
338e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor        } else {
339e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor            ret = NAME_NOT_FOUND;
340e14b37eb07b394fef05da5ee09dc6d33e3a25711Todd Poynor        }
3418f132af495d208272ea55d0ca24068926fa80e51Todd Poynor        break;
3428f132af495d208272ea55d0ca24068926fa80e51Todd Poynor
343c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    default:
344c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor        break;
345c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    }
346c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor
347c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor    return ret;
348c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor}
349c133b7198a02c8738aeef86d6cfd921a626adce7Todd Poynor
350020369d8724eff2b87350e54e157a609846166e4Todd Poynorvoid BatteryMonitor::dumpState(int fd) {
351020369d8724eff2b87350e54e157a609846166e4Todd Poynor    int v;
352020369d8724eff2b87350e54e157a609846166e4Todd Poynor    char vs[128];
353020369d8724eff2b87350e54e157a609846166e4Todd Poynor
354d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos    snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n",
355020369d8724eff2b87350e54e157a609846166e4Todd Poynor             props.chargerAcOnline, props.chargerUsbOnline,
356d5fe6675a73c3a831d0c4e41343ee86772633db8Adrian Roos             props.chargerWirelessOnline, props.maxChargingCurrent);
357020369d8724eff2b87350e54e157a609846166e4Todd Poynor    write(fd, vs, strlen(vs));
358020369d8724eff2b87350e54e157a609846166e4Todd Poynor    snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
359020369d8724eff2b87350e54e157a609846166e4Todd Poynor             props.batteryStatus, props.batteryHealth, props.batteryPresent);
360020369d8724eff2b87350e54e157a609846166e4Todd Poynor    write(fd, vs, strlen(vs));
361020369d8724eff2b87350e54e157a609846166e4Todd Poynor    snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n",
362020369d8724eff2b87350e54e157a609846166e4Todd Poynor             props.batteryLevel, props.batteryVoltage,
363020369d8724eff2b87350e54e157a609846166e4Todd Poynor             props.batteryTemperature);
364020369d8724eff2b87350e54e157a609846166e4Todd Poynor    write(fd, vs, strlen(vs));
365020369d8724eff2b87350e54e157a609846166e4Todd Poynor
366020369d8724eff2b87350e54e157a609846166e4Todd Poynor    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
367020369d8724eff2b87350e54e157a609846166e4Todd Poynor        v = getIntField(mHealthdConfig->batteryCurrentNowPath);
368020369d8724eff2b87350e54e157a609846166e4Todd Poynor        snprintf(vs, sizeof(vs), "current now: %d\n", v);
369020369d8724eff2b87350e54e157a609846166e4Todd Poynor        write(fd, vs, strlen(vs));
370020369d8724eff2b87350e54e157a609846166e4Todd Poynor    }
371020369d8724eff2b87350e54e157a609846166e4Todd Poynor
372020369d8724eff2b87350e54e157a609846166e4Todd Poynor    if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
373020369d8724eff2b87350e54e157a609846166e4Todd Poynor        v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
374020369d8724eff2b87350e54e157a609846166e4Todd Poynor        snprintf(vs, sizeof(vs), "current avg: %d\n", v);
375020369d8724eff2b87350e54e157a609846166e4Todd Poynor        write(fd, vs, strlen(vs));
376020369d8724eff2b87350e54e157a609846166e4Todd Poynor    }
377020369d8724eff2b87350e54e157a609846166e4Todd Poynor
378020369d8724eff2b87350e54e157a609846166e4Todd Poynor    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
379020369d8724eff2b87350e54e157a609846166e4Todd Poynor        v = getIntField(mHealthdConfig->batteryChargeCounterPath);
380020369d8724eff2b87350e54e157a609846166e4Todd Poynor        snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
381020369d8724eff2b87350e54e157a609846166e4Todd Poynor        write(fd, vs, strlen(vs));
382020369d8724eff2b87350e54e157a609846166e4Todd Poynor    }
383020369d8724eff2b87350e54e157a609846166e4Todd Poynor}
384020369d8724eff2b87350e54e157a609846166e4Todd Poynor
385c7464c9150eb63ad277cc5b5f704f4fd5e6678c5Todd Poynorvoid BatteryMonitor::init(struct healthd_config *hc) {
386752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 path;
3873db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor    char pval[PROPERTY_VALUE_MAX];
388752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
389f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor    mHealthdConfig = hc;
390752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
391752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (dir == NULL) {
392752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
393752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    } else {
394752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        struct dirent* entry;
395752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
396752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        while ((entry = readdir(dir))) {
397752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            const char* name = entry->d_name;
398752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
399752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            if (!strcmp(name, ".") || !strcmp(name, ".."))
400752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                continue;
401752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
402752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            // Look for "type" file in each subdirectory
403752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.clear();
404752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
405752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            switch(readPowerSupplyType(path)) {
406752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_AC:
407752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_USB:
408752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
409752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
410752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
411752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path.string(), R_OK) == 0)
412752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mChargerNames.add(String8(name));
413752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
414752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
415752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
4166dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor                mBatteryDevicePresent = true;
4176dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor
418f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryStatusPath.isEmpty()) {
419f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
420f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
421f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      name);
422f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0)
423f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryStatusPath = path;
424f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
425752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
426f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryHealthPath.isEmpty()) {
427752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
428f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
429f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      name);
430752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
431f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryHealthPath = path;
432752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
433752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
434f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryPresentPath.isEmpty()) {
435f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
436f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
437f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      name);
438f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0)
439f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryPresentPath = path;
440f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
441b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
442f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
443f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
444f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
445f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      name);
446f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0)
447f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryCapacityPath = path;
448f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
449b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
450f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
451f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
452f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/voltage_now",
453f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      POWER_SUPPLY_SYSFS_PATH, name);
454f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0) {
455f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryVoltagePath = path;
456f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    } else {
457f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        path.clear();
458f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        path.appendFormat("%s/%s/batt_vol",
459f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                          POWER_SUPPLY_SYSFS_PATH, name);
460f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        if (access(path, R_OK) == 0)
461f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                            mHealthdConfig->batteryVoltagePath = path;
462f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    }
463f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
464f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor
465f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
466752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
467f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/current_now",
468f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      POWER_SUPPLY_SYSFS_PATH, name);
469752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
470f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryCurrentNowPath = path;
471f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
472f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor
473bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
474bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                    path.clear();
475bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                    path.appendFormat("%s/%s/current_avg",
476bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                                      POWER_SUPPLY_SYSFS_PATH, name);
477bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                    if (access(path, R_OK) == 0)
478bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                        mHealthdConfig->batteryCurrentAvgPath = path;
479bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor                }
480bc102111845a48f79a4cf6ea058a0ca334cd613cTodd Poynor
481f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
482f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
483f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/charge_counter",
484f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      POWER_SUPPLY_SYSFS_PATH, name);
485f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0)
486f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryChargeCounterPath = path;
487f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
488f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor
489f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
490f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
491f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
492f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      name);
493f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0) {
494f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryTemperaturePath = path;
495f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    } else {
496f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        path.clear();
497f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        path.appendFormat("%s/%s/batt_temp",
498f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                          POWER_SUPPLY_SYSFS_PATH, name);
499f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        if (access(path, R_OK) == 0)
500f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                            mHealthdConfig->batteryTemperaturePath = path;
501f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    }
502f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                }
503f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor
504f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
505f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.clear();
506f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    path.appendFormat("%s/%s/technology",
507f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                                      POWER_SUPPLY_SYSFS_PATH, name);
508f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                    if (access(path, R_OK) == 0)
509f5d3012d2c6ac343a0b8bcc95b9cd5137d9ef02fTodd Poynor                        mHealthdConfig->batteryTechnologyPath = path;
510752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
511752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
512752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
513752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
514752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
515752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
516752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
517752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
518752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        closedir(dir);
519752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
520752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
521752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (!mChargerNames.size())
522752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
5236dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor    if (!mBatteryDevicePresent) {
524ebeb0c0ea63af9fd8b2c8a7a20f919e48098ad9aTodd Poynor        KLOG_WARNING(LOG_TAG, "No battery devices found\n");
5256dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        hc->periodic_chores_interval_fast = -1;
5266dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        hc->periodic_chores_interval_slow = -1;
5276dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor    } else {
5286dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryStatusPath.isEmpty())
5296dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
5306dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryHealthPath.isEmpty())
5316dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
5326dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryPresentPath.isEmpty())
5336dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
5346dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryCapacityPath.isEmpty())
5356dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
5366dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryVoltagePath.isEmpty())
5376dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
5386dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryTemperaturePath.isEmpty())
5396dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
5406dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor        if (mHealthdConfig->batteryTechnologyPath.isEmpty())
5416dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor            KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
5426dcc45ed6dd455d82ecfb3addf247125846f3019Todd Poynor    }
5433db03a5ab0cb7713529c298531be6da7c2193525Todd Poynor
544a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi    if (property_get("ro.boot.fake_battery", pval, NULL) > 0
545a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi                                               && strtol(pval, NULL, 10) != 0) {
546a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi        mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
547a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
548a78fc23491f3490bec4e4ac72c4bdc8c6d554fe3Ruchi Kandoi    }
549752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
550752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
551752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}; // namespace android
552