BatteryMonitor.cpp revision b45f1f5bd00c9a8380960d7c439eb14b3a334f50
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
19752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include "BatteryMonitor.h"
20752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include "BatteryPropertiesRegistrar.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>
30752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/String8.h>
31752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#include <utils/Vector.h>
32752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
33752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SUBSYSTEM "power_supply"
34752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
35752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
36752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynornamespace android {
37752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
38752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstruct sysfsStringEnumMap {
39752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char* s;
40752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int val;
41752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor};
42752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
43752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorstatic int mapSysfsString(const char* str,
44752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                          struct sysfsStringEnumMap map[]) {
45752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    for (int i = 0; map[i].s; i++)
46752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (!strcmp(str, map[i].s))
47752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            return map[i].val;
48752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
49752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return -1;
50752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
51752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
52752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryStatus(const char* status) {
53752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
54752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryStatusMap[] = {
55752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_STATUS_UNKNOWN },
56752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Charging", BATTERY_STATUS_CHARGING },
57752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Discharging", BATTERY_STATUS_DISCHARGING },
58752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
59752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Full", BATTERY_STATUS_FULL },
60752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
61752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
62752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
63752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryStatusMap);
64752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
65752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
66752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_STATUS_UNKNOWN;
67752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
68752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
69752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
70752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
71752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
72752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getBatteryHealth(const char* status) {
73752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int ret;
74752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap batteryHealthMap[] = {
75752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unknown", BATTERY_HEALTH_UNKNOWN },
76752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Good", BATTERY_HEALTH_GOOD },
77752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Overheat", BATTERY_HEALTH_OVERHEAT },
78752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Dead", BATTERY_HEALTH_DEAD },
79752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
80752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
81752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { "Cold", BATTERY_HEALTH_COLD },
82752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        { NULL, 0 },
83752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
84752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
85752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = mapSysfsString(status, batteryHealthMap);
86752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0) {
87752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
88752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = BATTERY_HEALTH_UNKNOWN;
89752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
90752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
91752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
92752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
93752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
94752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
95752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char *cp = NULL;
96752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
97752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (path.isEmpty())
98752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
99752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int fd = open(path.string(), O_RDONLY, 0);
100752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (fd == -1) {
101752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
102752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return -1;
103752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
104752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
105752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
106752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (count > 0)
107752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            cp = (char *)memrchr(buf, '\n', count);
108752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
109752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (cp)
110752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        *cp = '\0';
111752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
112752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        buf[0] = '\0';
113752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
114752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    close(fd);
115752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return count;
116752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
117752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
118752faf2c18407fd79127fb3f3773910b4ddf669dTodd PoynorBatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
119752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
120752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
121752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int length = readFromFile(path, buf, SIZE);
122752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    BatteryMonitor::PowerSupplyType ret;
123752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct sysfsStringEnumMap supplyTypeMap[] = {
124752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
125752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
126752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
127752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
128752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
129752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
130752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
131752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
132752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
133752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            { NULL, 0 },
134752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    };
135752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
136752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (length <= 0)
137752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
138752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
139752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
140752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (ret < 0)
141752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
142752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
143752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return ret;
144752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
145752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
146752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::getBooleanField(const String8& path) {
147752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 16;
148752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
149752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
150752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    bool value = false;
151752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
152752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (buf[0] != '0') {
153752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            value = true;
154752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
155752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
156752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
157752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
158752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
159752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
160752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorint BatteryMonitor::getIntField(const String8& path) {
161752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
162752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
163752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
164752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    int value = 0;
165752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(path, buf, SIZE) > 0) {
166752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        value = strtol(buf, NULL, 0);
167752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
168752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return value;
169752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
170752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
171752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorbool BatteryMonitor::update(void) {
172752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    struct BatteryProperties props;
173752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
174752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerAcOnline = false;
175752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerUsbOnline = false;
176752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.chargerWirelessOnline = false;
177752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
178752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
179b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    props.batteryCurrentNow = INT_MIN;
180b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    props.batteryChargeCounter = INT_MIN;
181752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
182752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (!mBatteryPresentPath.isEmpty())
183752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryPresent = getBooleanField(mBatteryPresentPath);
184752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    else
185752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryPresent = true;
186752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
187752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryLevel = getIntField(mBatteryCapacityPath);
188752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryVoltage = getIntField(mBatteryVoltagePath) / 1000;
189b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
190b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    if (!mBatteryCurrentNowPath.isEmpty())
191b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        props.batteryCurrentNow = getIntField(mBatteryCurrentNowPath) / 1000;
192b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
193b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    if (!mBatteryChargeCounterPath.isEmpty())
194b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        props.batteryChargeCounter = getIntField(mBatteryChargeCounterPath) / 1000;
195b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
196752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    props.batteryTemperature = getIntField(mBatteryTemperaturePath);
197752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
198752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    const int SIZE = 128;
199752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    char buf[SIZE];
200752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 btech;
201752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
202752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryStatusPath, buf, SIZE) > 0)
203752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryStatus = getBatteryStatus(buf);
204752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
205752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryHealthPath, buf, SIZE) > 0)
206752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryHealth = getBatteryHealth(buf);
207752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
208752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (readFromFile(mBatteryTechnologyPath, buf, SIZE) > 0)
209752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        props.batteryTechnology = String8(buf);
210752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
211752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    unsigned int i;
212752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
213752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    for (i = 0; i < mChargerNames.size(); i++) {
214752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        String8 path;
215752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
216752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                          mChargerNames[i].string());
217752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
218752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        if (readFromFile(path, buf, SIZE) > 0) {
219752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            if (buf[0] != '0') {
220752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
221752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
222752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                                  mChargerNames[i].string());
223752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                switch(readPowerSupplyType(path)) {
224752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_AC:
225752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerAcOnline = true;
226752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
227752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_USB:
228752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerUsbOnline = true;
229752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
230752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
231752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    props.chargerWirelessOnline = true;
232752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    break;
233752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                default:
234752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
235752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                                 mChargerNames[i].string());
236752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
237752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
238752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
239752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
240752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
241b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    char dmesgline[256];
242b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    snprintf(dmesgline, sizeof(dmesgline),
243b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
244b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             props.batteryLevel, props.batteryVoltage,
245b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             props.batteryTemperature < 0 ? "-" : "",
246b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             abs(props.batteryTemperature / 10),
247b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             abs(props.batteryTemperature % 10), props.batteryHealth,
248b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor             props.batteryStatus);
249b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
250b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    if (!mBatteryCurrentNowPath.isEmpty()) {
251b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        char b[20];
252b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
253b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow);
254b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor        strlcat(dmesgline, b, sizeof(dmesgline));
255b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    }
256b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
257b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor    KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
258752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor              props.chargerAcOnline ? "a" : "",
259752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor              props.chargerUsbOnline ? "u" : "",
260752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor              props.chargerWirelessOnline ? "w" : "");
261752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
262752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryPropertiesRegistrar != NULL)
263752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        mBatteryPropertiesRegistrar->notifyListeners(props);
264752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
265752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    return props.chargerAcOnline | props.chargerUsbOnline |
266752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            props.chargerWirelessOnline;
267752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
268752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
269752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynorvoid BatteryMonitor::init(bool nosvcmgr) {
270752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    String8 path;
271752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
272752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
273752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (dir == NULL) {
274752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
275752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    } else {
276752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        struct dirent* entry;
277752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
278752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        while ((entry = readdir(dir))) {
279752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            const char* name = entry->d_name;
280752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
281752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            if (!strcmp(name, ".") || !strcmp(name, ".."))
282752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                continue;
283752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
284752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            char buf[20];
285752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            // Look for "type" file in each subdirectory
286752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.clear();
287752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
288752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            switch(readPowerSupplyType(path)) {
289752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_AC:
290752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_USB:
291752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
292752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
293752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
294752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path.string(), R_OK) == 0)
295752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mChargerNames.add(String8(name));
296752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
297752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
298752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
299752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
300752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, name);
301752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
302752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryStatusPath = path;
303752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
304752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name);
305752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
306752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryHealthPath = path;
307752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
308752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, name);
309752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
310752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryPresentPath = path;
311752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
312752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH, name);
313752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
314752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryCapacityPath = path;
315752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
316752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
317752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_SYSFS_PATH, name);
318752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0) {
319752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryVoltagePath = path;
320752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                } else {
321752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
322752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.appendFormat("%s/%s/batt_vol", POWER_SUPPLY_SYSFS_PATH, name);
323752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
324752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                            mBatteryVoltagePath = path;
325752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
326752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
327752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
328b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.appendFormat("%s/%s/current_now", POWER_SUPPLY_SYSFS_PATH, name);
329b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                if (access(path, R_OK) == 0)
330b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                    mBatteryCurrentNowPath = path;
331b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
332b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.clear();
333b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.appendFormat("%s/%s/charge_counter", POWER_SUPPLY_SYSFS_PATH, name);
334b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                if (access(path, R_OK) == 0)
335b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                    mBatteryChargeCounterPath = path;
336b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor
337b45f1f5bd00c9a8380960d7c439eb14b3a334f50Todd Poynor                path.clear();
338752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH, name);
339752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0) {
340752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryTemperaturePath = path;
341752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                } else {
342752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.clear();
343752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    path.appendFormat("%s/%s/batt_temp", POWER_SUPPLY_SYSFS_PATH, name);
344752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    if (access(path, R_OK) == 0)
345752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                            mBatteryTemperaturePath = path;
346752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                }
347752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
348752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.clear();
349752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                path.appendFormat("%s/%s/technology", POWER_SUPPLY_SYSFS_PATH, name);
350752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                if (access(path, R_OK) == 0)
351752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                    mBatteryTechnologyPath = path;
352752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
353752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
354752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
355752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor                break;
356752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            }
357752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        }
358752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        closedir(dir);
359752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
360752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
361752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (!mChargerNames.size())
362752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
363752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryStatusPath.isEmpty())
364752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
365752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryHealthPath.isEmpty())
366752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING("BatteryHealthPath not found\n");
367752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryPresentPath.isEmpty())
368752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
369752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryCapacityPath.isEmpty())
370752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
371752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryVoltagePath.isEmpty())
372752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
373752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryTemperaturePath.isEmpty())
374752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
375752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (mBatteryTechnologyPath.isEmpty())
376752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor        KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
377752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
378752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    if (nosvcmgr == false) {
379752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
380752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor            mBatteryPropertiesRegistrar->publish();
381752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor    }
382752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}
383752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor
384752faf2c18407fd79127fb3f3773910b4ddf669dTodd Poynor}; // namespace android
385