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