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