BatteryMonitor.cpp revision 10b235e7436256da9adc827125645f141bd8fac9
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#include "BatteryPropertiesRegistrar.h"
22752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
23752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <dirent.h>
24752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <errno.h>
25752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <fcntl.h>
26752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <stdio.h>
27752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <stdlib.h>
28752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <unistd.h>
29752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <batteryservice/BatteryService.h>
30752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <cutils/klog.h>
31752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/String8.h>
32752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/Vector.h>
33752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
34752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SUBSYSTEM "power_supply"
35752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
36752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
37752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynornamespace android {
38752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
39752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstruct sysfsStringEnumMap {
40752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char* s;
41752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int val;
42752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor};
43752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
44752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstatic int mapSysfsString(const char* str,
45752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                          struct sysfsStringEnumMap map[]) {
46752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    for (int i = 0; map[i].s; i++)
47752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (!strcmp(str, map[i].s))
48752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            return map[i].val;
49752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
50752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return -1;
51752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
52752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
53752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryStatus(const char* status) {
54752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
55752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryStatusMap[] = {
56752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_STATUS_UNKNOWN },
57752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Charging", BATTERY_STATUS_CHARGING },
58752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Discharging", BATTERY_STATUS_DISCHARGING },
59752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
60752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Full", BATTERY_STATUS_FULL },
61752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
62752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
63752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
64752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryStatusMap);
65752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
66752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
67752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_STATUS_UNKNOWN;
68752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
69752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
70752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
71752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
72752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
73752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryHealth(const char* status) {
74752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
75752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryHealthMap[] = {
76752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_HEALTH_UNKNOWN },
77752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Good", BATTERY_HEALTH_GOOD },
78752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Overheat", BATTERY_HEALTH_OVERHEAT },
79752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Dead", BATTERY_HEALTH_DEAD },
80752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
81752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
82752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Cold", BATTERY_HEALTH_COLD },
83752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
84752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
85752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
86752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryHealthMap);
87752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
88752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
89752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_HEALTH_UNKNOWN;
90752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
91752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
92752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
93752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
94752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
95752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
96752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char *cp = NULL;
97752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
98752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (path.isEmpty())
99752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
100752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int fd = open(path.string(), O_RDONLY, 0);
101752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (fd == -1) {
102752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
103752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
104752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
105752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
106752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
107752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (count > 0)
108752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            cp = (char *)memrchr(buf, '\n', count);
109752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
110752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (cp)
111752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        *cp = '\0';
112752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
113752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        buf[0] = '\0';
114752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
115752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    close(fd);
116752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return count;
117752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
118752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
119752faf2c18407fd79127fb3f3773910b4ddf669dTodd PoynorBatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
120752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
121752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
122752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int length = readFromFile(path, buf, SIZE);
123752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    BatteryMonitor::PowerSupplyType ret;
124752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap supplyTypeMap[] = {
125752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
126752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
127752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
128752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
129752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
130752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
131752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
132752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
133752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
134752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { NULL, 0 },
135752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
136752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
137752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (length <= 0)
138752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
139752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
140752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
141752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0)
142752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
143752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
144752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
145752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
146752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
147752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::getBooleanField(const String8& path) {
148752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 16;
149752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
150752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
151752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    bool value = false;
152752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
153752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (buf[0] != '0') {
154752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            value = true;
155752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
156752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
157752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
158752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
159752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
160752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
161752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getIntField(const String8& path) {
162752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
163752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
164752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
165752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int value = 0;
166752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
167752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        value = strtol(buf, NULL, 0);
168752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
169752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
170752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
171752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
172752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::update(void) {
173752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct BatteryProperties props;
17410b235e7436256da9adc827125645f141bd8fac9Todd Poynor    bool logthis;
175752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
176752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerAcOnline = false;
177752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerUsbOnline = false;
178752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerWirelessOnline = false;
179752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
180752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
181b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    props.batteryCurrentNow = INT_MIN;
182b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    props.batteryChargeCounter = INT_MIN;
183752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
184752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (!mBatteryPresentPath.isEmpty())
185752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryPresent = getBooleanField(mBatteryPresentPath);
186752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
187752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryPresent = true;
188752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
189752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryLevel = getIntField(mBatteryCapacityPath);
190752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryVoltage = getIntField(mBatteryVoltagePath) / 1000;
191b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
192b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    if (!mBatteryCurrentNowPath.isEmpty())
193b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        props.batteryCurrentNow = getIntField(mBatteryCurrentNowPath) / 1000;
194b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
195b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    if (!mBatteryChargeCounterPath.isEmpty())
196b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        props.batteryChargeCounter = getIntField(mBatteryChargeCounterPath) / 1000;
197b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
198752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryTemperature = getIntField(mBatteryTemperaturePath);
199752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
200752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
201752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
202752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 btech;
203752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
204752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryStatusPath, buf, SIZE) > 0)
205752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryStatus = getBatteryStatus(buf);
206752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
207752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryHealthPath, buf, SIZE) > 0)
208752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryHealth = getBatteryHealth(buf);
209752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
210752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryTechnologyPath, 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                }
239752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
240752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
241752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
242752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
24310b235e7436256da9adc827125645f141bd8fac9Todd Poynor    logthis = !healthd_board_battery_update(&props);
244b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
24510b235e7436256da9adc827125645f141bd8fac9Todd Poynor    if (logthis) {
24610b235e7436256da9adc827125645f141bd8fac9Todd Poynor        char dmesgline[256];
24710b235e7436256da9adc827125645f141bd8fac9Todd Poynor        snprintf(dmesgline, sizeof(dmesgline),
24810b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
24910b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryLevel, props.batteryVoltage,
25010b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryTemperature < 0 ? "-" : "",
25110b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 abs(props.batteryTemperature / 10),
25210b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 abs(props.batteryTemperature % 10), props.batteryHealth,
25310b235e7436256da9adc827125645f141bd8fac9Todd Poynor                 props.batteryStatus);
254b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
25510b235e7436256da9adc827125645f141bd8fac9Todd Poynor        if (!mBatteryCurrentNowPath.isEmpty()) {
25610b235e7436256da9adc827125645f141bd8fac9Todd Poynor            char b[20];
25710b235e7436256da9adc827125645f141bd8fac9Todd Poynor
25810b235e7436256da9adc827125645f141bd8fac9Todd Poynor            snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow);
25910b235e7436256da9adc827125645f141bd8fac9Todd Poynor            strlcat(dmesgline, b, sizeof(dmesgline));
26010b235e7436256da9adc827125645f141bd8fac9Todd Poynor        }
261b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
26210b235e7436256da9adc827125645f141bd8fac9Todd Poynor        KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
26310b235e7436256da9adc827125645f141bd8fac9Todd Poynor                  props.chargerAcOnline ? "a" : "",
26410b235e7436256da9adc827125645f141bd8fac9Todd Poynor                  props.chargerUsbOnline ? "u" : "",
26510b235e7436256da9adc827125645f141bd8fac9Todd Poynor                  props.chargerWirelessOnline ? "w" : "");
26610b235e7436256da9adc827125645f141bd8fac9Todd Poynor    }
267752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
268752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryPropertiesRegistrar != NULL)
269752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        mBatteryPropertiesRegistrar->notifyListeners(props);
270752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
271752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return props.chargerAcOnline | props.chargerUsbOnline |
272752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            props.chargerWirelessOnline;
273752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
274752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
275752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorvoid BatteryMonitor::init(bool nosvcmgr) {
276752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 path;
277752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
278752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
279752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (dir == NULL) {
280752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
281752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    } else {
282752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        struct dirent* entry;
283752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
284752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        while ((entry = readdir(dir))) {
285752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            const char* name = entry->d_name;
286752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
287752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            if (!strcmp(name, ".") || !strcmp(name, ".."))
288752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                continue;
289752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
290752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            char buf[20];
291752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            // Look for "type" file in each subdirectory
292752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.clear();
293752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
294752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            switch(readPowerSupplyType(path)) {
295752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_AC:
296752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_USB:
297752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
298752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
299752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
300752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path.string(), R_OK) == 0)
301752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mChargerNames.add(String8(name));
302752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
303752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
304752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
305752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
306752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, name);
307752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
308752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryStatusPath = path;
309752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
310752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name);
311752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
312752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryHealthPath = path;
313752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
314752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, name);
315752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
316752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryPresentPath = path;
317752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
318752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH, name);
319752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
320752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryCapacityPath = path;
321752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
322752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
323752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_SYSFS_PATH, name);
324752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0) {
325752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryVoltagePath = path;
326752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                } else {
327752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
328752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.appendFormat("%s/%s/batt_vol", POWER_SUPPLY_SYSFS_PATH, name);
329752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
330752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                            mBatteryVoltagePath = path;
331752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
332752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
333752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
334b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.appendFormat("%s/%s/current_now", POWER_SUPPLY_SYSFS_PATH, name);
335b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                if (access(path, R_OK) == 0)
336b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                    mBatteryCurrentNowPath = path;
337b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
338b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.clear();
339b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.appendFormat("%s/%s/charge_counter", POWER_SUPPLY_SYSFS_PATH, name);
340b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                if (access(path, R_OK) == 0)
341b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                    mBatteryChargeCounterPath = path;
342b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
343b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.clear();
344752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH, name);
345752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0) {
346752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryTemperaturePath = path;
347752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                } else {
348752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
349752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.appendFormat("%s/%s/batt_temp", POWER_SUPPLY_SYSFS_PATH, name);
350752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
351752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                            mBatteryTemperaturePath = path;
352752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
353752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
354752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
355752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/technology", POWER_SUPPLY_SYSFS_PATH, name);
356752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
357752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryTechnologyPath = path;
358752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
359752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
360752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
361752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
362752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
363752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
364752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        closedir(dir);
365752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
366752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
367752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (!mChargerNames.size())
368752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
369752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryStatusPath.isEmpty())
370752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
371752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryHealthPath.isEmpty())
372752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING("BatteryHealthPath not found\n");
373752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryPresentPath.isEmpty())
374752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
375752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryCapacityPath.isEmpty())
376752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
377752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryVoltagePath.isEmpty())
378752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
379752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryTemperaturePath.isEmpty())
380752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
381752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryTechnologyPath.isEmpty())
382752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
383752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
384752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (nosvcmgr == false) {
385752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
386752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            mBatteryPropertiesRegistrar->publish();
387752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
388752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
389752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
390752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}; // namespace android
391