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